package com.common.utils;



import com.common.ErrorCodeEnum;
import com.common.exception.BusinessException;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.JWT;
import com.auth0.jwt.exceptions.JWTDecodeException;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.client.RestTemplate;


import java.lang.reflect.Field;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

public  class Utils {
    /**
     * @Author: zql
     * @Description: 生成4位随机数
     * @param
     * @Data: 9:07 2021/7/13
     */
    public static String vCode() {
        StringBuilder vCode = new StringBuilder();
        for (int i = 0; i < 4; i++) {
            vCode.append((int) (Math.random() * 9));
        }
        return vCode.toString();
    }

    /** 生成指定长度的密码*/
    public static String getRandKeys( int intLength ) {
        String retStr;  //生成的密码
        String strTable = "23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz";
        //密码使用符号，可更改
        int len = strTable.length();
        //生成结束标志
        boolean bDone = false;
        do {
            retStr = "";
            //生成密码中数字的个数
            int count = 0;
            //生成密码中字母的个数
            int count1 = 0;
            //生成密码中符号的个数
            int count2 = 0;
            for ( int i = 0; i < intLength; i++ ) {
                int intR = (int) Math.floor( Math.random() * len );
                //找到指定字符
                char c = strTable.charAt( intR );
                //判断字符类型并计数：数字，字母，符号
                if ( ( '0' <= c ) && ( c <= '9' ) ) {
                    count++;
                } else if ( ( 'A' <= c ) && ( c <= 'z' ) ) {
                    count1++;
                } else
                {
                    count2++;
                }
                retStr += strTable.charAt( intR );
            }
            if ( count >= 1 && count1>=4 && count2>=0) {
                //如果符号密码强度，则置结束标志：密码至少包含1个数字，4个字母，1个符号
                bDone = true;
            }
        } while ( !bDone );
        return retStr;
    }

    /**
     * 字符串是否包含英文+数字
     *
     * @param str 待校验字符串
     * @return true 合法ID false 有非法字符
     */
    public static boolean isLegalID(String str) {
        return str.matches("^[a-zA-Z0-9]+[a-zA-Z0-9_]*[a-zA-Z0-9]+$");
    }

    /**
     * 返回信息
     *
     * @return
     */
    public static JSONObject result(ErrorCodeEnum errorCodeEnum, Object obj) {

        JSONObject result = new JSONObject();
        result.put("code", errorCodeEnum.getErrorCode());
        result.put("message", errorCodeEnum.getErrorMsg());
        result.put("data", obj);
        return result;
    }

    /**
     * 返回信息
     *
     * @return
     */
    public static JSONObject result(ErrorCodeEnum errorCodeEnum) {
        JSONObject result = new JSONObject();
        result.put("code", errorCodeEnum.getErrorCode());
        result.put("message", errorCodeEnum.getErrorMsg());
        result.put("data", null);
        return result;
    }


    /**
     * 采用POST请求，数据格式为 application/json，并且返回结果是JSON string
     *
     * @param url
     * @param
     * @return
     */
    public static String httpPostForJson(RestTemplate restTemplate, String url, JSONObject json) {
        //新建RestTemplate对象
        //RestTemplate restTemplate = new RestTemplate();
        //解决中文乱码问题
        //restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        //设置Http Header
        HttpHeaders headers = new HttpHeaders();
        //设置请求媒体数据类型
        headers.setContentType(MediaType.APPLICATION_JSON);
        //设置返回媒体数据类型
        headers.add("Accept", MediaType.APPLICATION_JSON.toString());
        HttpEntity<String> formEntity = new HttpEntity<String>(json.toString(), headers);
        return restTemplate.postForObject(url, formEntity, String.class);
    }

    public static String httpGet(RestTemplate restTemplate, String url) {
        return restTemplate.getForObject(url, String.class);
    }

    /**
     * GET 时间格式为EEE, dd MMM yyyy HH:mm:ss z 例如Wed, 18 Dec 2019 02:35:02 GMT
     *
     * @return String
     */
    public static String getTime() {
        Date d = new Date();
        DateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
        format.setTimeZone(TimeZone.getTimeZone("GMT"));
        String hdate = format.format(d);
        return hdate;
    }

    public static Long getTokenUserId(String token) throws BusinessException {
        try {
            return Long.valueOf(JWT.decode(token).getAudience().get(0));
        } catch (JWTDecodeException j) {
            throw new BusinessException(ErrorCodeEnum.UNAUTHORIZED);
        }
    }

    public static String  getTokenUserName(String token) throws BusinessException {
        try {
            return JWT.decode(token).getAudience().get(1);
        } catch (JWTDecodeException j) {
            throw new BusinessException(ErrorCodeEnum.UNAUTHORIZED);
        }
    }

//    public static KeyType getKeyType(String keyType){
//        if(keyType.equals(Constants.ED25519)){
//            return KeyType.ED25519;
//        }
//        if(keyType.equals(Constants.SM2)){
//            return KeyType.ECCSM2;
//        }
//        return KeyType.ED25519;
//    }

//    /**
//     * 利用MD5进行加密
//     */
//    public static String EncoderByMd5(String str) throws NoSuchAlgorithmException, UnsupportedEncodingException {
//        //确定计算方法
//        MessageDigest md5 = MessageDigest.getInstance("MD5");
//        BASE64Encoder base64en = new BASE64Encoder();
//        //加密后的字符串
//        String newstr = base64en.encode(md5.digest(str.getBytes("utf-8")));
//        return newstr;
//    }
//
//    /**
//     * 判断用户密码是否正确
//     * newpasswd 用户输入的密码
//     * oldpasswd 正确密码
//     */
//    public static boolean checkPassword(String newpasswd, String oldpasswd) throws NoSuchAlgorithmException, UnsupportedEncodingException {
//        if (EncoderByMd5(newpasswd).equals(oldpasswd))
//            return true;
//        else
//            return false;
//    }
    /**
     * 判断手机号或座机是否合法，手机号长度为11位
     * @param mobile 手机号
     * */
    public static boolean isMobileNO(String mobile) {
//        String telRegex = "[1-9][1-9]\\d{9}";
        String telRegex = "^((0\\d{2,3}-\\d{7,8})|([1-9][1-9]\\d{9}))$";
        // "[1-9]"代表第1位为数字1~9，"[3578]"代表第二位可以为3、5、8中的一个，"\\d{9}"代表后面是可以是0～9的数字，有9位。
        if (StringUtils.isEmpty(mobile)) {
            return false;
        } else{
            return mobile.matches(telRegex);
        }
    }

    /**
     * 判断性别是否合法，性别只能填'男'或'女'
     * @param gender 性别
     * */
    public static boolean isGenderNO(String gender) {
        String telRegex = "(男|女)";
        if (StringUtils.isEmpty(gender)) {
            return false;
        } else{
            return gender.matches(telRegex);
        }
    }

    /**
     * @Author: zql
     * @Description:校验对象中成员是否有null
     * @param o
     * @param filterNames 被排除允许有null的成员列表
     * @Data: 14:43 2021/7/2
     */
    public static String verifyNullMember(Object o,String ... filterNames){
        Field[] fields=o.getClass().getDeclaredFields();
        for(Field field:fields ) {
            field.setAccessible(true);
            if(Arrays.stream(filterNames).anyMatch(filterName->field.getName().equals(filterName))){
                continue;
            }
            try {
                if (StringUtils.isNull(field.get(o)) ) {
                    return field.getName();
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
                throw new BusinessException(ErrorCodeEnum.VERIFY_NULL_FAILED.setParam(field.getName()));
            }
        }
        return "";
    }

    /**
     * @Author: zql
     * @Description: 磁盘字节转换 进制1000
     * @param size
     * @Data: 2021-07-14
     * @return: java.lang.String
     */
        public static String getPrintSize(long size) {
            //如果字节数少于1000，则直接以B为单位，否则先除于1000，后3位因太少无意义
            if (size < 1000) {
                return String.valueOf(size) + "B";
            } else {
                size = size / 1000;
            }
            //如果原字节数除于1000之后，少于1000，则可以直接以KB作为单位
            //因为还没有到达要使用另一个单位的时候
            //接下去以此类推
            if (size < 1000) {
                return String.valueOf(size) + "KB";
            } else {
                size = size / 1000;
            }
            if (size < 1000) {
                //因为如果以MB为单位的话，要保留最后1位小数，
                //因此，把此数乘以100之后再取余
                size = size * 100;
                return String.valueOf((size / 100)) + "."
                        + String.valueOf((size % 100)) + "MB";
            } else {
                //否则如果要以GB为单位的，先除于1000再作同样的处理
                size = size * 100 / 1000;
                return String.valueOf((size / 100)) + "."
                        + String.valueOf((size % 100)) + "GB";
            }
        }

    }
